import { toFixed } from "../common/Util";

export class Vector2 {
    x = 0;
    y = 0;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    /** 加上 */
    plus(vector: Vector2) {
        return new Vector2(this.x + vector.x, this.y + vector.y);
    }

    /** 减去 */
    minus(vector: Vector2) {
        return new Vector2(this.x - vector.x, this.y - vector.y);
    }

    /** 乘法 */
    multiply(vector: Vector2) {
        return toFixed(this.x * vector.x) + toFixed(this.y * vector.y)
    }

    /** 缩放 */
    scale(k: number) {
        return new Vector2(toFixed(this.x * k), toFixed(this.y * k));
    }

    copy(v: Vector2) {
        this.x = v.x;
        this.y = v.y;
        return this;
    }

    clone() {
        return new Vector2(this.x, this.y);
    }

    subtract(out: Vector2, other: Vector2) {
        out.x -= other.x;
        out.y -= other.y;
        return out;
    }

    /** 长度的平方 */
    lengthSqr() {
        return toFixed(this.x ** 2) + toFixed(this.y ** 2);
    }
}

/** 障碍物 */
export class Obstacle {
    constructor() {
        this.next = null;//下一个
        this.previous = null;//前一个
        this.direction = new Vector2(1, 0);//方向
        this.point = new Vector2(0, 0);//坐标
        this.id = 0;
        this.convex = true;//凸出的
    }
    next: Obstacle | null;//下一个
    previous: Obstacle | null;//前一个
    direction: Vector2;//方向
    point: Vector2;//坐标
    id: number;
    convex: boolean;//凸出的
}

export class Line {
    constructor() {
        this.point = new Vector2(0, 0)
        this.direction = new Vector2(0, 0)
    }
    point: Vector2;
    direction: Vector2;
}

export class KeyValuePair<K, V> {
    key: K;
    value: V;
    constructor(key: K, value: V) {
        this.key = key;
        this.value = value;
    }
}

export class RVOMath {

    /** 值越大，扎堆概率越小 */
    static RVO_EPSILON = 0.1;

    /** 平方 */
    static absSq(v: Vector2) {
        return v.multiply(v);
    };

    /** 归一化 */
    static normalize(v: Vector2) {
        let v2 = v.scale(1 / RVOMath.abs(v));
        v2.x = toFixed(v2.x)
        v2.y = toFixed(v2.y)
        return v2
    };

    static distSqPointLineSegment(vector1: Vector2, vector2: Vector2, vector3: Vector2) {
        let aux1 = vector3.minus(vector1);
        let aux2 = vector2.minus(vector1);

        let r = toFixed(aux1.multiply(aux2) / RVOMath.absSq(aux2));

        if (r < 0) {
            return RVOMath.absSq(aux1);
        }
        else if (r > 1) {
            return RVOMath.absSq(vector3.minus(vector2));
        }
        else {
            return RVOMath.absSq(vector3.minus(vector1.plus(aux2.scale(r))));
        }
    };

    static sqr(p: number) {
        return toFixed(p * p);
    };

    static det(v1: Vector2, v2: Vector2) {
        return toFixed(v1.x * v2.y) - toFixed(v1.y * v2.x);
    };

    /** 绝对值 */
    static abs(v: Vector2) {
        return Math.sqrt(RVOMath.absSq(v));
    };

    static leftOf(a: Vector2, b: Vector2, c: Vector2) {
        return RVOMath.det(a.minus(c), b.minus(a));
    };

}